﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace hamster
{
    public class Scene
    {
        VertexPositionNormalTexture[] _wheel;
        Effect _grassEffect;
        Effect _backgroundEffect;
        Texture2D _grassTexture;
        Texture2D _backgroundTexture;
        float _times;


        public void Create(ContentManager content)
        {
            _grassEffect = content.Load<Effect>("Grass");
            _backgroundEffect = content.Load<Effect>("Background");
            _grassTexture = content.Load<Texture2D>("color_grass");
            _backgroundTexture = content.Load<Texture2D>("twilight");


            //Draw the grass
            matrices = new Matrix[80];

            for (int i = 0; i < matrices.Length; i++)
            {

                float f = (float)i / (float)matrices.Length;
                float a = f * (float)Math.PI * 2f;
                float r = (float)Math.Sin(a * 5.74f);

                Matrix scale = Matrix.CreateScale(
                    (float)Game1.RandomFloat * 0.3f + 0.6f,
                    (float)Game1.RandomFloat * 0.45f + 0.3f,
                    (float)Game1.RandomFloat * 0.3f + 0.6f
                    );

                matrices[i] = scale * Matrix.CreateRotationY(Game1.RandomFloat - 0.5f) * Matrix.CreateRotationZ(1.545f) * Matrix.CreateTranslation(8.5f, 0, 1.5f) * Matrix.CreateRotationZ(a);
            } 
        }

        public void Reload(ContentManager content)
        {
            if (_grassEffect != null) _grassEffect.Dispose();
            if (_grassTexture != null) _grassTexture.Dispose();
            if (_backgroundEffect != null) _backgroundEffect.Dispose();
            if (_backgroundTexture != null) _backgroundTexture.Dispose();

            Create(content);
        }
        public VertexPositionNormalTexture[] ComputeWheelGeometry()
        {
            int bits = 2;
            float grass_width = 4f;
            float grass_height = 3f;

            VertexPositionNormalTexture[] wheel = new VertexPositionNormalTexture[6 * bits];
            for (int i = 0; i < bits; i++)
            {
                float frac_xn = ((float)i / (float)bits);
                float frac_xm = ((float)(1 + i) / (float)bits);
                ///////////////
                wheel[i * 6 + 0] = new VertexPositionNormalTexture
                {
                    Position = new Vector3(grass_width * -.5f, frac_xn * grass_height, 0f),
                    TextureCoordinate = new Vector2(0f, 1f-frac_xn)
                };

                wheel[i * 6 + 1] = new VertexPositionNormalTexture
                {
                    Position = new Vector3(grass_width * .5f, frac_xn * grass_height, 0f),
                    TextureCoordinate = new Vector2(1f, 1f-frac_xn),
                    
                };

                wheel[i * 6 + 2] = new VertexPositionNormalTexture
                {
                    Position = new Vector3(grass_width * .5f, frac_xm * grass_height, 0f),
                    TextureCoordinate = new Vector2(1f, 1f-frac_xm)
                };
                ////
                wheel[i * 6 + 3] = new VertexPositionNormalTexture
                {
                    Position = new Vector3(grass_width * -.5f, frac_xn * grass_height, 0f),
                    TextureCoordinate = new Vector2(0f,1f -frac_xn)
                };

                wheel[i * 6 + 4] = new VertexPositionNormalTexture
                {
                    Position = new Vector3(grass_width * .5f, frac_xm * grass_height, 0f),
                    TextureCoordinate = new Vector2(1f,1f -frac_xm)
                };

                wheel[i * 6 + 5] = new VertexPositionNormalTexture
                {
                    Position = new Vector3(grass_width * -.5f, frac_xm * grass_height, 0f),
                    TextureCoordinate = new Vector2(0f,1f -frac_xm)
                }; 

            }

            return wheel;
        }

        public void Update(float dt)
        {
            _wheel = ComputeWheelGeometry();
            _times += dt;
        }


        public void DrawGlow(GraphicsDevice device)
        {
            _backgroundEffect.Parameters["View"].SetValue(Game1.viewMatrix);
            _backgroundEffect.Parameters["Projection"].SetValue(Game1.projectionMatrix);
            _backgroundEffect.Parameters["UserTexture"].SetValue(_backgroundTexture);
            //Draw the background
            _backgroundEffect.Begin();
            _backgroundEffect.CurrentTechnique.Passes[1].Begin();


            float depth = -5;
            float rad = 1;
            VertexPositionNormalTexture[] _quad = new VertexPositionNormalTexture[6] {
                new VertexPositionNormalTexture { Position = new Vector3(-rad,-rad,depth) },
                new VertexPositionNormalTexture { Position = new Vector3(rad,-rad,depth) },
                new VertexPositionNormalTexture { Position = new Vector3(rad,rad,depth) },
                new VertexPositionNormalTexture { Position = new Vector3(-rad,-rad,depth) },
                new VertexPositionNormalTexture { Position = new Vector3(rad,rad,depth) },
                new VertexPositionNormalTexture { Position = new Vector3(-rad,rad,depth) }
            };

            device.DrawUserPrimitives<VertexPositionNormalTexture>(
                      PrimitiveType.TriangleList,
                      _quad,
                      0,
                      _quad.Length / 3
                  );
            _backgroundEffect.CurrentTechnique.Passes[1].End();
            _backgroundEffect.End();
        }


        public void DrawBackground(GraphicsDevice device)
        {
            _backgroundEffect.Parameters["View"].SetValue(Game1.viewMatrix);
            _backgroundEffect.Parameters["Projection"].SetValue(Game1.projectionMatrix);
            _backgroundEffect.Parameters["UserTexture"].SetValue(_backgroundTexture);
            //Draw the background
            _backgroundEffect.Begin();
            _backgroundEffect.CurrentTechnique.Passes[0].Begin();


            float depth = -5;
            float rad = 1;
            VertexPositionNormalTexture[] _quad = new VertexPositionNormalTexture[6] {
                new VertexPositionNormalTexture { Position = new Vector3(-rad,-rad,depth) },
                new VertexPositionNormalTexture { Position = new Vector3(rad,-rad,depth) },
                new VertexPositionNormalTexture { Position = new Vector3(rad,rad,depth) },
                new VertexPositionNormalTexture { Position = new Vector3(-rad,-rad,depth) },
                new VertexPositionNormalTexture { Position = new Vector3(rad,rad,depth) },
                new VertexPositionNormalTexture { Position = new Vector3(-rad,rad,depth) }
            };

            device.DrawUserPrimitives<VertexPositionNormalTexture>(
                      PrimitiveType.TriangleList,
                      _quad,
                      0,
                      _quad.Length / 3
                  );
            _backgroundEffect.CurrentTechnique.Passes[0].End();
            _backgroundEffect.End();
        }

        Matrix[] matrices;
        public void Draw(GraphicsDevice device) {

            DrawGrass(device, matrices);
        }

        public void DrawGrass(GraphicsDevice device, Matrix[] matrices)
        {
            device.RenderState.DepthBufferWriteEnable = false;
            device.RenderState.AlphaBlendEnable = true;
            device.RenderState.SourceBlend = Blend.SourceAlpha;
            device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;

            _grassEffect.Parameters["Time"].SetValue(_times);
            _grassEffect.Parameters["View"].SetValue(Game1.viewMatrix);
            _grassEffect.Parameters["Projection"].SetValue(Game1.projectionMatrix);
            _grassEffect.Parameters["UserTexture"].SetValue(_grassTexture);
            _grassEffect.Begin();

            foreach (EffectPass pass in _grassEffect.CurrentTechnique.Passes)
            {

                foreach (Matrix m in matrices)
                {
                    _grassEffect.Parameters["World"].SetValue(m);//.CreateRotationZ(_angleInRadians));
                    _grassEffect.CommitChanges();

                    pass.Begin();
                    device.DrawUserPrimitives<VertexPositionNormalTexture>(
                        PrimitiveType.TriangleList,
                        _wheel,
                        0,
                        _wheel.Length / 3
                    );
                    pass.End();
                }
            }

            _grassEffect.End();
            device.RenderState.DepthBufferWriteEnable = true;
            device.RenderState.AlphaBlendEnable = false;
        }
    }
}
